package cn.itcast.web.aspect;

import cn.itcast.domain.system.SysLog;
import cn.itcast.domain.system.User;
import cn.itcast.service.system.SysLogService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;

/**
 * 自动记录日志的切面类
 */
@Component
@Aspect     // 标注一个切面类
public class LogAspect {

    @Autowired
    private SysLogService sysLogService;
    @Autowired
    private HttpServletRequest request;

    /**
     * 自动记录日志的方法：获取方法名、方法所在的类
     * 使用哪种通知? 环绕
     * 切入点表达式：
     * execution(* cn..UserServiceImpl.save())
     * |-- 表示拦截cn包及其所有子包下的UserServiceImpl类的save方法
     * |-- cn.. 省略包及其子包
     * |-- execution(* com..*.*(..))  会拦截到jar包中的一些（jar包中的很多类都是com开头的）
     * 最好不要这样些，建议写全一点：com.itheima..
     */
    @Around("execution(* cn.itcast.web.controller..*.*(..))")
    public Object insertLog(ProceedingJoinPoint pjp) {
        try {
            // 放行，执行目标对象的方法（控制器的方法）
            Object retV = pjp.proceed();

            // 访问者的ip
            String ip = request.getRemoteAddr();
            User user = (User) request.getSession().getAttribute("loginUser");
            String userName = "";
            String companyId = "";
            String companyName = "";
            if (user != null) {
                userName = user.getUserName();
                companyId = user.getCompanyId();
                companyName = user.getCompanyName();
            }

            // 记录日志
            //SysLog sysLog = new SysLog();
            //sysLog.setId("");
            SysLog log = SysLog.builder().userName(userName)
                    .ip(ip)
                    .time(new Date())
                    .method(pjp.getSignature().getName()) // 当前执行的方法名称
                    .action(pjp.getTarget().getClass().getName()) // 目标对象全名
                    .companyId(companyId)
                    .companyName(companyName).build();

            sysLogService.save(log);
            return retV;
        } catch (Throwable throwable) {
            // 这里必须转换为运行时期异常并抛出
            throw new RuntimeException(throwable);
        }
    }
}
